home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 July: Mac OS SDK / Dev.CD Jul 96 SDK / Dev.CD Jul 96 SDK1.toast / Development Kits (Disc 1) / AOCE / Development Tools / Sample Code / Messaging Service Access Module / Internet PMSAM / Internet PMSAM source / spooltoaoce.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-21  |  13.4 KB  |  463 lines  |  [TEXT/MPS ]

  1. /*-------------------------------------------------------------------
  2.  
  3. AOCE Post Office Protocol (POP) / Simple Mail Transfer Protocol (SMTP)
  4. Mail Service Access Module
  5.  
  6. written by Steve Falkenburg-- MacDTS
  7. ©1991-1993 Apple Computer, Inc.
  8.  
  9. --------------
  10. change history
  11. --------------
  12.  
  13. SJF        02/19/93    update for beta build    b1
  14. SJF        02/19/93    update for beta build    b1
  15. SJF        10/29/92    update to a11            a11
  16. SJF        06/08/92    update to a8            a8
  17. SJF        02/15/92    first working version    a4.5
  18. SJF        10/16/91    initial coding            a3
  19.  
  20. ---------------------------------------------------------------------*/
  21.  
  22. #ifndef __TYPES__
  23. #include <Types.h>
  24. #endif
  25.  
  26. #ifndef __OCE__
  27. #include <OCE.h>
  28. #endif
  29.  
  30. #ifndef __OCEMAIL__
  31. #include <OCEMail.h>
  32. #endif
  33.  
  34. #include <string.h>
  35.  
  36. #include "const.h"
  37. #include "gwerrors.h"
  38. #include "mytypes.h"
  39. #include "globals.h"
  40. #include "utils.h"
  41. #include "spoolsystem.h"
  42. #include "gatewaystuff.h"
  43. #include "spooltoaoce.h"
  44.  
  45. #define    kDefaultSubject            "<no subject>"
  46. #define kDefaultSubjectLength    12
  47. #define    kDefaultBody            "<no message>"
  48. #define kDefaultBodyLength        12
  49.  
  50. #define    kMaxRStringPostIt        kRString32Size-4    // maximum length of sender, subject in postit
  51. #define    kLetterCreator            'lap2'
  52.  
  53.  
  54. // SpoolIntoAOCE
  55. //
  56. // this function is called to retrieve an external message from the spool area and submit
  57. // it into the incoming queue via the toolbox.  it first creates a post-it for the message
  58. // and then creates the actual message and inserts the message data.  if we wanted to be an
  59. // "on-line" gateway, we would just create the post-it and not the message.  we would then get
  60. // a message opened eppc when the user double-clicked and would have to download the message
  61. // in response.
  62. //
  63. OSErr SpoolIntoAOCE(FSSpec *spoolSpec,SlotSpec *slot)
  64. {
  65.     OSErr err;
  66.     MSAMParam gwp;
  67.     unsigned long macSecs;
  68.     MSAMMsgSummary postIt;
  69.     Ptr dataBuffer;
  70.     unsigned long bufferLen;
  71.     RString subject;
  72.     RecordID entitySpecifier;
  73.     DSSpec fromAddress;
  74.     MailMsgRef mailRef;
  75.     long msgSeqNum;
  76.     unsigned char *subjectOffset;
  77.     long blockIndex,contentLength;
  78.     short contentTypeIndex;
  79.     OSType contentTypes[kNumContentTypes] = {kTextContent,kPictContent,kSoundContent,
  80.                                             kStyledTextContent,kMovieContent};
  81.     TraceExecution("\pSpoolIntoAOCE");
  82.         
  83.     // allocate buffer for spooling from disk
  84.     
  85.     bufferLen = kMaxBufferSize;
  86.     dataBuffer = NewPtrChk(bufferLen);
  87.     if (MemError()!=noErr)
  88.         return MemError();
  89.  
  90.     
  91.     // get length of message data in bytes (for message summary info)
  92.     
  93.     contentLength = 0;
  94.     for (blockIndex=0,err=noErr; err==noErr; blockIndex++) {
  95.         err = kNoData;
  96.         for (contentTypeIndex=0; (err!=noErr) && (contentTypeIndex<kNumContentTypes); contentTypeIndex++) {
  97.             err = GetSpoolLength(spoolSpec,contentTypes[contentTypeIndex],kContentCreator,blockIndex,&bufferLen);
  98.             if (err==noErr)
  99.             contentLength += bufferLen;
  100.         }
  101.     }
  102.         
  103.     // ********** create the post-it (msg summary) for the message **************************
  104.     
  105.     ClearBuffer(&postIt,sizeof(MSAMMsgSummary));
  106.     postIt.version = kMailMsgSummaryVersion;
  107.     postIt.masterData.attrMask.sendTimeStamp = true;
  108.     postIt.masterData.attrMask.indications = true;
  109.     postIt.masterData.attrMask.from = true;
  110.     postIt.masterData.attrMask.subject = true;
  111.     postIt.masterData.attrMask.msgType = true;
  112.     postIt.masterData.attrMask.msgFamily = true;
  113.         
  114.     GetDateTime(&macSecs);                                                // time
  115.     MacToMailTime(macSecs,&postIt.coreData.sendTime);
  116.     *(long *)&postIt.coreData.letterIndications = 0;
  117.     postIt.coreData.letterIndications.priority = kIPMNormalPriority;    // indications
  118.     postIt.coreData.letterIndications.hasContent = true;                // true since we have cont.
  119.     postIt.coreData.messageType.msgType = kMailLtrMsgType;                // message type
  120.     postIt.coreData.messageType.msgCreator = kLetterCreator;            // message creator
  121.     postIt.coreData.messageFamily = kMailFamily;                        // family of message
  122.     postIt.coreData.messageSize = contentLength;                        // size of message
  123.     postIt.coreData.addressedToMe = kAddressedAs_TO;                    // we faked this...
  124.  
  125.     // get subject
  126.     
  127.     bufferLen = sizeof(RString);
  128.     err = GetFromSpool(spoolSpec,kSubjectType,kAttribCreator,0,(Ptr)&subject,&bufferLen,0);
  129.     if (err!=noErr)
  130.         OCECToRString(kDefaultSubject,smRoman,(RStringPtr)&subject,kRStringMaxBytes);
  131.     OCECopyFitRString((RStringPtr)&subject,(RStringPtr)&postIt.coreData.subject,kMaxRStringPostIt);
  132.         
  133.     // get from name
  134.     
  135.     bufferLen = kMaxBufferSize;
  136.     err = GetFromSpool(spoolSpec,kFromType,kAddrCreator,0,dataBuffer,&bufferLen,0);
  137.     if (err!=noErr) {
  138.         DisposPtrChk(dataBuffer);
  139.         return err;
  140.     }
  141.     OCEUnpackDSSpec((PackedDSSpec*)dataBuffer,&fromAddress,&entitySpecifier);
  142.     OCECopyFitRString(entitySpecifier.local.recordName,(RStringPtr)&postIt.coreData.sender,kMaxRStringPostIt);
  143.     
  144.     // move subject flush with sender RString (pack them together as close as possible even pad)
  145.     
  146.     subjectOffset = ((unsigned char *)&postIt.coreData.sender)+postIt.coreData.sender.dataLength+sizeof(long);
  147.     if ((unsigned long)subjectOffset % 2)
  148.         subjectOffset++;
  149.     BlockMove(&postIt.coreData.subject,subjectOffset,postIt.coreData.subject.dataLength+sizeof(long));
  150.     
  151.     // make the message summary
  152.     
  153.     gwp.header.ioCompletion = (ProcPtr)MSAMCompletion;
  154.     gwp.pmsamCreateMsgSummary.inQueueRef = slot->inQueue;
  155.     gwp.pmsamCreateMsgSummary.msgSummary = &postIt;
  156.     gwp.pmsamCreateMsgSummary.buffer = nil;
  157.     PMSAMCreateMsgSummary(&gwp,true);
  158.     err = WaitPBDone(&gwp);
  159.     if (err!=noErr) {
  160.         DisposPtrChk(dataBuffer);
  161.         return err;
  162.     }
  163.     msgSeqNum = gwp.pmsamCreateMsgSummary.seqNum;
  164.     
  165.     // ********** create the message (submit the actual data **************************
  166.  
  167.     // check to see if we have bcc recipients
  168.     
  169.  
  170.     // first, really create the messsage
  171.     
  172.     bufferLen = kMaxBufferSize;
  173.     err = GetFromSpool(spoolSpec,kBCCType,kAddrCreator,0,dataBuffer,&bufferLen,0);
  174.     gwp.msamCreate.bccRecipients = (err==noErr);    // do we have bcc recipients?
  175.     gwp.msamCreate.queueRef = slot->inQueue;
  176.     gwp.msamCreate.seqNum = msgSeqNum;
  177.     gwp.msamCreate.asLetter = true;
  178.     gwp.msamCreate.msgType.format = kIPMOSFormatType;
  179.     gwp.msamCreate.msgType.theType.msgOSType.msgCreator = kLetterCreator;
  180.     gwp.msamCreate.msgType.theType.msgOSType.msgType = kMailLtrMsgType;
  181.     gwp.msamCreate.tunnelForm = false;
  182.     MSAMCreate(&gwp,true);
  183.     err = WaitPBDone(&gwp);
  184.     if (err!=noErr) {
  185.         DisposPtrChk(dataBuffer);
  186.         return err;
  187.     }
  188.     mailRef = gwp.msamCreate.newRef;
  189.     
  190.     // add the time
  191.     
  192.     gwp.msamPutAttribute.mailMsgRef = mailRef;
  193.     gwp.msamPutAttribute.attrID = kMailSendTimeStampBit;
  194.     gwp.msamPutAttribute.buffer.buffer = (Ptr)&postIt.coreData.sendTime;
  195.     gwp.msamPutAttribute.buffer.bufferSize = sizeof(MailTime);
  196.     MSAMPutAttribute(&gwp,true);
  197.     err = WaitPBDone(&gwp);
  198.     if (err!=noErr) {
  199.         BailOnSubmit(mailRef,msgSeqNum,slot->inQueue,dataBuffer);
  200.         return err;
  201.     }
  202.     
  203.     // add the message family
  204.     
  205.     gwp.msamPutAttribute.mailMsgRef = mailRef;
  206.     gwp.msamPutAttribute.attrID = kMailMsgFamilyBit;
  207.     gwp.msamPutAttribute.buffer.buffer = (Ptr)&postIt.coreData.messageFamily;
  208.     gwp.msamPutAttribute.buffer.bufferSize = sizeof(OSType);
  209.     MSAMPutAttribute(&gwp,true);
  210.     err = WaitPBDone(&gwp);
  211.     if (err!=noErr) {
  212.         BailOnSubmit(mailRef,msgSeqNum,slot->inQueue,dataBuffer);
  213.         return err;
  214.     }
  215.  
  216.     // add the indications
  217.     
  218.     gwp.msamPutAttribute.mailMsgRef = mailRef;
  219.     gwp.msamPutAttribute.attrID = kMailIndicationsBit;
  220.     gwp.msamPutAttribute.buffer.buffer = (Ptr)&postIt.coreData.letterIndications;
  221.     gwp.msamPutAttribute.buffer.bufferSize = sizeof(MailIndications);
  222.     MSAMPutAttribute(&gwp,true);
  223.     err = WaitPBDone(&gwp);
  224.     if (err!=noErr) {
  225.         BailOnSubmit(mailRef,msgSeqNum,slot->inQueue,dataBuffer);
  226.         return err;
  227.     }
  228.     
  229.     // add the recipients
  230.     
  231.     err = AddTheRecipients(mailRef,spoolSpec,kFromType,kMailFromBit,dataBuffer,kMaxBufferSize);
  232.     if (err!=noErr) {
  233.         BailOnSubmit(mailRef,msgSeqNum,slot->inQueue,dataBuffer);
  234.         return err;
  235.     }
  236.  
  237.     err = AddTheRecipients(mailRef,spoolSpec,kToType,kMailToBit,dataBuffer,kMaxBufferSize);
  238.     if (err!=noErr) {
  239.         BailOnSubmit(mailRef,msgSeqNum,slot->inQueue,dataBuffer);
  240.         return err;
  241.     }
  242.         
  243.     err = AddTheRecipients(mailRef,spoolSpec,kCCType,kMailCcBit,dataBuffer,kMaxBufferSize);
  244.     if (err!=noErr) {
  245.         BailOnSubmit(mailRef,msgSeqNum,slot->inQueue,dataBuffer);
  246.         return err;
  247.     }
  248.     
  249.     err = AddTheRecipients(mailRef,spoolSpec,kBCCType,kMailBccBit,dataBuffer,kMaxBufferSize);
  250.     if (err!=noErr) {
  251.         BailOnSubmit(mailRef,msgSeqNum,slot->inQueue,dataBuffer);
  252.         return err;
  253.     }
  254.  
  255.     // add the subject
  256.     
  257.     gwp.msamPutAttribute.mailMsgRef = mailRef;
  258.     gwp.msamPutAttribute.attrID = kMailSubjectBit;
  259.     gwp.msamPutAttribute.buffer.buffer = (Ptr)&subject;
  260.     gwp.msamPutAttribute.buffer.bufferSize = subject.dataLength+4;
  261.     if ((gwp.msamPutAttribute.buffer.bufferSize%2)!=0)
  262.         gwp.msamPutAttribute.buffer.bufferSize++;
  263.     MSAMPutAttribute(&gwp,true);
  264.     err = WaitPBDone(&gwp);
  265.     if (err!=noErr) {
  266.         BailOnSubmit(mailRef,msgSeqNum,slot->inQueue,dataBuffer);
  267.         return err;
  268.     }
  269.  
  270.     // add content
  271.     
  272.     err = SpoolContentsToAOCE(spoolSpec,mailRef,dataBuffer);
  273.     if (err!=noErr) {
  274.         BailOnSubmit(mailRef,msgSeqNum,slot->inQueue,dataBuffer);
  275.         return err;
  276.     }
  277.     
  278.     // submit the letter
  279.     
  280.     gwp.msamSubmit.mailMsgRef = mailRef;
  281.     gwp.msamSubmit.submitFlag = true;    // submit letter
  282.     err = MSAMSubmit(&gwp);
  283.         
  284.     DisposPtrChk(dataBuffer);
  285.  
  286.     if (err!=noErr) {
  287.         /* delete post-it */
  288.         
  289.         gwp.header.ioCompletion = (ProcPtr)MSAMCompletion;                    
  290.         gwp.msamDelete.queueRef  = slot->inQueue;
  291.         gwp.msamDelete.seqNum = msgSeqNum;
  292.         gwp.msamDelete.msgOnly = false;
  293.         gwp.msamDelete.result = noErr;    // server gw only
  294.         MSAMDelete(&gwp,true);
  295.         WaitPBDone(&gwp);
  296.     }
  297.  
  298.     return err;
  299. }
  300.  
  301.  
  302. void BailOnSubmit(MailMsgRef mailRef,long seqNum,MSAMQueueRef queueRef,Ptr dataBuffer)
  303. {
  304.     MSAMParam gwp;
  305.  
  306.     TraceExecution("\pbail out");
  307.  
  308.     /* delete message */
  309.     
  310.     DisposPtrChk(dataBuffer);
  311.     gwp.msamSubmit.mailMsgRef = mailRef;
  312.     gwp.msamSubmit.submitFlag = false;        // abort letter
  313.     MSAMSubmit(&gwp);
  314.     
  315.     /* delete post-it */
  316.     
  317.     gwp.header.ioCompletion = (ProcPtr)MSAMCompletion;                    
  318.     gwp.msamDelete.queueRef  = queueRef;
  319.     gwp.msamDelete.seqNum = seqNum;
  320.     gwp.msamDelete.msgOnly = false;
  321.     gwp.msamDelete.result = noErr;    // server gw only
  322.     MSAMDelete(&gwp,true);
  323.     WaitPBDone(&gwp);
  324. }
  325.  
  326.  
  327. OSErr AddTheRecipients(MailMsgRef mailRef,FSSpec *spoolSpec,OSType recipType,MailAttributeID attrID,Ptr dataBuffer,unsigned long bufferLen)
  328. {
  329.     OSErr err;
  330.     Boolean moreRecipients = true;
  331.     short index;
  332.     unsigned long gotLength;
  333.     DSSpec recipient;
  334.     RecordID entitySpecifier;
  335.     MSAMParam gwp;
  336.     
  337.     index = 0;
  338.     
  339.     do {
  340.         
  341.         gotLength = bufferLen;
  342.         err = GetFromSpool(spoolSpec,recipType,kAddrCreator,index,dataBuffer,&gotLength,0);
  343.         if (err==noErr && gotLength>0) {
  344.             
  345.             // submit one recipient
  346.             
  347.             OCEUnpackDSSpec((PackedDSSpec*)dataBuffer,&recipient,&entitySpecifier);
  348.             gwp.msamPutRecipient.ioCompletion = (ProcPtr)MSAMCompletion;
  349.             gwp.msamPutRecipient.mailMsgRef = mailRef;
  350.             gwp.msamPutRecipient.attrID = attrID;
  351.             gwp.msamPutRecipient.recipient = &recipient;
  352.             gwp.msamPutRecipient.responsible = false;        // always false for PMSAMs
  353.             MSAMPutRecipient(&gwp,true);
  354.             err = WaitPBDone(&gwp);
  355.  
  356.         }
  357.         else {
  358.             moreRecipients = false;
  359.             err = noErr;
  360.         }
  361.         
  362.         index++;
  363.     } while (err==noErr && moreRecipients);
  364.     
  365.     return err;
  366. }
  367.  
  368.  
  369. OSErr SpoolContentsToAOCE(FSSpec *spoolSpec,MailMsgRef mailRef,Ptr dataBuffer)
  370. {
  371.     long blockIndex,blockOffset;
  372.     unsigned long bufferLen;
  373.     OSType contentType;
  374.     Boolean contentSpooled,startOfBlock;
  375.     MSAMParam gwp;
  376.     OSErr err,err2;
  377.     
  378.     gwp.header.ioCompletion = (ProcPtr)MSAMCompletion;
  379.     gwp.msamPutContent.mailMsgRef = mailRef;
  380.     gwp.msamPutContent.textScrap = nil;
  381.     gwp.msamPutContent.buffer.buffer = dataBuffer;
  382.     gwp.msamPutContent.script = smRoman;
  383.     
  384.     blockIndex = 0;
  385.     contentType = kTextContent;
  386.     contentSpooled = false;
  387.     startOfBlock = true;
  388.     
  389.     // for each segment block...
  390.     do {
  391.         blockOffset = 0;
  392.         
  393.         // for each piece of a segment block
  394.         do {
  395.             bufferLen = kMaxBufferSize;                
  396.             err = GetFromSpool(spoolSpec,contentType,kContentCreator,blockIndex,
  397.                         dataBuffer,&bufferLen,blockOffset);
  398.             
  399.             // set up parameter block
  400.             
  401.             if (startOfBlock) {
  402.                 switch (contentType) {
  403.                     case kTextContent:
  404.                         gwp.msamPutContent.segmentType = kMailTextSegmentType;
  405.                         if (blockIndex==0)
  406.                             gwp.msamPutContent.startNewScript = true;
  407.                         break;
  408.                     case kPictContent:
  409.                         gwp.msamPutContent.segmentType = kMailPictSegmentType;
  410.                         break;
  411.                     case kSoundContent:
  412.                         gwp.msamPutContent.segmentType = kMailSoundSegmentType;
  413.                         break;
  414.                     case kStyledTextContent:
  415.                         gwp.msamPutContent.segmentType = kMailStyledTextSegmentType;
  416.                         if (blockIndex==0)
  417.                             gwp.msamPutContent.startNewScript = true;
  418.                         break;
  419.                     case kMovieContent:
  420.                         gwp.msamPutContent.segmentType = kMailMovieSegmentType;
  421.                         break;
  422.                 }
  423.             }
  424.             gwp.msamPutContent.append = !startOfBlock;
  425.             gwp.msamPutContent.buffer.bufferSize = bufferLen;
  426.             
  427.             // make putcontent call
  428.             
  429.             if ((err==noErr)||(err==kMoreData)) {
  430.                 MSAMPutContent(&gwp,true);
  431.                 err2 = WaitPBDone(&gwp);
  432.                 if (err2!=noErr)
  433.                     return err;
  434.                 contentSpooled = true;        // we spooled some content (don't need default text)
  435.             }
  436.             
  437.             blockOffset += bufferLen;    // increment block offset
  438.             startOfBlock = false;        // we're not at the start of a block
  439.             
  440.         } while (err==kMoreData);
  441.         
  442.         blockIndex++;                    // increment block index
  443.         startOfBlock = true;            // we're at the start of a block again
  444.         
  445.     } while (err!=noErr);
  446.     
  447.     if (err==kNoData)
  448.         err = noErr;
  449.         
  450.     // if no content was spooled, spool some default content so AOCE will accept the letter
  451.     
  452.     if (contentSpooled==false) {
  453.         strcpy(dataBuffer,kDefaultBody);
  454.         gwp.msamPutContent.segmentType = kMailTextSegmentType;
  455.         gwp.msamPutContent.append = false;
  456.         gwp.msamPutContent.buffer.bufferSize = strlen(kDefaultBody);
  457.         MSAMPutContent(&gwp,true);
  458.         err = WaitPBDone(&gwp);
  459.     }
  460.     
  461.     return err;
  462. }
  463.